// 通过该 文件 来进入我们的 高效率内存分配器
#include "common.hpp"
#include "threadCache.hpp"

class MemoryAllocator
{
public:
    // TLS 无锁申请空间访问
    static void* enterAlloc(size_t bytes)
    {
        //通过TLS，每个线程无锁的获取自己专属的ThreadCache对象
        // if(pTLSThreadCache == nullptr){
        //     pTLSThreadCache = new ThreadCache;
        // }
        // return pTLSThreadCache->allocateMem(bytes);

        if(bytes > ThreadCache_Max_Bytes)   // 大于 256 KB 的内存申请
        {
            // 1.计算出 对齐后需要 申请的页数
            size_t alignSize = Util::roundUp(bytes);
            size_t kPage = alignSize >> Page_Shift; // 计算出需要的页数
            // 2, 向 PageCache 申请 kPage 页的 Span
            PageCache::getInstance()->getPageMutex().lock();    // 加大锁
            Span* span = PageCache::getInstance()->c_getKSpanFromPageCache(kPage);
            PageCache::getInstance()->getPageMutex().unlock();  // 解大锁

            // 3. 直接返回
            void* ptr = (void*)(span->page_id << Page_Shift);
            return ptr;
        }
        else{
            //通过TLS，每个线程无锁的获取自己专属的ThreadCache对象
            if(pTLSThreadCache == nullptr){
                // pTLSThreadCache = new ThreadCache;
                static std:mutex tcMtx;
                static objectPool<ThreadCache> tcPool;
                tcMtx.lock();
                pTLSThreadCache = tcPool.New(); // 从内存池中申请一个 ThreadCache
                tcMtx.unlock();
            }
            return pTLSThreadCache->allocateMem(bytes);
        }
    }

    // free this memory
    static void freeMem(void* ptr)
    {
        Span* span = PageCache::getInstance()->objToSpanMap(ptr);
        size_t bytes = span->objSize; // 获取该 span 中小块内存的大小
        if(bytes > ThreadCache_Max_Bytes)
        {     
            PageCache::getInstance()->getPageMutex().lock();    // 加大锁
            PageCache::getInstance()->c_returnSpanToPageCache(span);
            PageCache::getInstance()->getPageMutex().unlock();  // 解大锁
        }
        else{
            assert(pTLSThreadCache);
            pTLSThreadCache->deallocateMem(ptr, bytes);
        }
        // pTLSThreadCache

    }
};